JNI便捷开发框架JNA框架之指针参数Pointer(二)

您所在的位置:网站首页 java size函数 JNI便捷开发框架JNA框架之指针参数Pointer(二)

JNI便捷开发框架JNA框架之指针参数Pointer(二)

2023-08-24 21:37| 来源: 网络整理| 查看: 265

一、背景

上一篇介绍了JNA框架开发的入门,项目是基于JNA框架开发,本文的焦点是参数的地址传递。 在java中都是值传递,但是因为使用JNA框架,目标函数是C/C++是有地址变量的,很多时候都需要将变量的结果带回,因此,地址传递在JNA项目中几乎是必须的。

二、案例代码

C/C++

/** * 返回a+b的值 * 同时c和msg通过参数返回 */ int add(int a, int b, int *c, char **msg) { *c = (a + b) * 2; char *string = "hello world!"; *msg = string; return a + b; }

如果java这样写

public class HelloJNA { /** * 定义一个接口,默认的是继承Library ,如果动态链接库里的函数是以stdcall方式输出的,那么就继承StdCallLibrary * 这个接口对应一个动态链接(SO)文件 */ public interface LibraryAdd extends Library { // 这里使用绝对路径加载 LibraryAdd LIBRARY_ADD = Native.load("/program/cpp/libhello.so", LibraryAdd.class); int add(int a, int b, int c, String msg); } public static void main(String[] args) { int c = 0; String msg = "start"; // 调用so映射的接口函数 int add = LibraryAdd.LIBRARY_ADD.add(10, 15, c, msg); System.out.println("相加结果:" + add); } }

那么不管add函数对c和msg做了何种改变,返回java中,值都不会被变更。

三、指针参数Pointer

那么如何实现类似C语言那样的地址传递,或者说指针传递呢?在JNA框架中,我们可以借助一个类完成,他就是Pointer。 com.sun.jna.Pointer,指针数据类型,用于匹配转换映射函数的指针变量。

1、定义 Pointer c = new Memory(50); Pointer msg = new Memory(50);

说明: 这样的指针变量定义很像C的写法,就是在定义的时候申请空间。比如这里就申请50个空间 根据测试结果对于字符串,一个空间对于两个字符左右。如果返回的结果长度比分配的空间大,则会报错

Exception in thread “main” java.lang.IndexOutOfBoundsException: Bounds exceeds available space : size=6, offset=8

最后可以这样释放申请的空间

Native.free(Pointer.nativeValue(c)); //手动释放内存 Pointer.nativeValue(c, 0); //避免Memory对象被GC时重复执行Nativ.free()方法 Native.free(Pointer.nativeValue(msg)); Pointer.nativeValue(msg, 0); 2、使用 import com.sun.jna.Library; import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.Pointer; /** * 一个java类 * 演示指针传输指针变量 */ public class HelloJNA_Pointer { /** * 定义一个接口,默认的是继承Library ,如果动态链接库里的函数是以stdcall方式输出的,那么就继承StdCallLibrary * 这个接口对应一个动态链接(SO)文件 */ public interface LibraryAdd extends Library { LibraryAdd LIBRARY_ADD = Native.load("/program/cpp/libhello.so", LibraryAdd.class); /** * 指针变量,用Pointer类型定义 * c是int* * msg是char** */ int add_c(int a, int b, Pointer c, Pointer msg); } public static void main(String[] args) { Pointer c = new Memory(50); Pointer msg = new Memory(8); // 调用so映射的接口函数 int add = LibraryAdd.LIBRARY_ADD.add_c(10, 15, c, msg); System.out.println("相加结果:" + add); // 指针变量 System.out.println("c的值:" + c.getInt(0)); // 这样才能拿到 System.out.println("msg的值:" + msg.getPointer(0).getString(0)); Native.free(Pointer.nativeValue(c)); //手动释放内存 Pointer.nativeValue(c, 0); //避免Memory对象被GC时重复执行Nativ.free()方法 Native.free(Pointer.nativeValue(msg)); //手动释放内存 Pointer.nativeValue(msg, 0); //避免Memory对象被GC时重复执行Nativ.free()方法 } }

说明: ①、传递参数直接传Pointer 定义出来的对象即可 ②、取值时,需要根据变量的类型采用不同的API读取,例如,如果函数是int*变量,那么就c.getInt(0) 如果是char **msg,就msg.getPointer(0).getString(0) ③、指针说明:一层指针就直接取值c.getInt(0),其中0表示偏移量从0开始;如果是二级指针,msg.getPointer(0).getString(0),表示指针的指针再取值;多级指针以此类推。

3、运行结果 [root@192 cpp]# java -jar JNATestC.jar 相加结果:25 c的值:50 msg的值:hello world! 四、最后

项目搭建请回看:JNI便捷开发框架JNA框架之入门(一) 有个知识点参考:C语言中字符串变量的函数值传递与指针传递

– – –

上一篇 JNI便捷开发框架JNA框架之入门(一) 下一篇JNI便捷开发框架JNA框架之参数引用传递ByReference(三)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3